/**
 * 每个节点没有up只有子节点
 */
var Node = {
    //类变量和方法
    createNew: function (id, 名称) {
        let self = { id: id, name: 名称, up: null, children: [] }
        return self;
    },
    /**
     * json必须是对象而不是数组  children 必须是数组
     * 结构表 第一个是id字段名, 第二项是name字段名 第三项是children字段名, 第四项开始是 其他属性
     */
    json2Object: function (json, 结构表, up) {
        if (json == null) return null;
        let 结构 = 结构表 || ["id", "name", "children"];
        let obj = {};
        obj.id = json[结构[0]];
        obj.name = json[结构[1]];
        obj.up = up;
        obj.children = [];
        for (let index = 3; index < 结构.length; index++) {
            const key = 结构[index];
            if (json.hasOwnProperty(key))
                obj[key] = json[key];
        }
        if (json.hasOwnProperty(结构[2])) {
            let children = json[结构[2]];
            if (children)
                for (let i = 0; i < children.length; ++i) {
                    let c = this.json2Object(children[i], 结构, obj);
                    if (c) obj.children.push(c);
                }
        }
        return obj;
    },
    /**
    * obj必须是对象而不是数组  children 必须是数组
    * 结构表 第一个是id字段名, 第二项是name字段名 第三项是children字段名, 第四项开始是 其他属性
    */
    object2Json: function (obj, 结构表) {
        if (obj == null) return null;
        // let 类型=Object.prototype.toString.call(obj);
        // if (类型!="[object Object]") return null;
        let 结构 = 结构表 || ["id", "name", "children"];
        let json = {};
        json[结构[0]] = obj.id;
        json[结构[1]] = obj.name;
        json[结构[2]] = [];
        for (let index = 3; index < 结构.length; index++) {
            const key = 结构[index];
            if (obj.hasOwnProperty(key))
                json[key] = obj[key];
        }
        if (obj.hasOwnProperty(结构[2])) {
            let children = obj[结构[2]];
            if (children)
                for (let i = 0; i < children.length; ++i) {
                    let c = this.object2Json(children[i], 结构);
                    if (c) json[结构[2]].push(c);
                }
        }
        return json;
    },
    /**
       * json必须是数组  children 必须是数组
       * 结构表 第一个是id字段名, 第二项是name字段名 第三项是children字段名, 第四项开始是 其他属性
       */
    json2Array: function (json, 结构表, up) {
        if (json == null) return null;
        let 结构 = 结构表 || ["id", "name", "children"];
        let arr = [];
        for (let i = 0; i < json.length; ++i) {
            let obj2 = json[i];
            let obj = {};
            obj.id = obj2[结构[0]];
            obj.name = obj2[结构[1]];
            obj.up = up;
            for (let index = 3; index < 结构.length; index++) {
                const key = 结构[index];
                if (obj2.hasOwnProperty(key))
                    obj[key] = obj2[key];
            }
            if (obj2.hasOwnProperty(结构[2]) && obj2[结构[2]]) {
                obj.children = this.json2Array(obj2[结构[2]], 结构, obj);
            }
            arr.push(obj)
        }
        return arr;
    },

    /**
     * json必须是数组  children 必须是数组
     * 结构表 第一个是id字段名, 第二项是name字段名 第三项是children字段名, 第四项开始是 其他属性
     */
    array2Json: function (arr, 结构表) {
        if (arr == null) return null;
        let 结构 = 结构表 || ["id", "name", "children"];
        let json = []
        for (let i = 0; i < arr.length; ++i) {
            let obj2 = arr[i];
            let obj = {};
            obj[结构[0]] = obj2.id;
            obj[结构[1]] = obj2.name;
            for (let index = 3; index < 结构.length; index++) {
                const key = 结构[index];
                if (obj2.hasOwnProperty(key))
                    obj[key] = obj2[key];
            }
            if (obj2.hasOwnProperty(结构[2]) && obj2[结构[2]]) {
                obj[结构[2]] = this.array2Json(obj2[结构[2]], 结构);
            }
            json.push(obj);
        }
        return json;
    },

    add子节点: function (节点, 子节点) {
        if (节点 && 子节点) {
            节点.children.push(子节点);
            子节点.up = 节点
        }
    },
    chg子节点: function (节点, 第n个子节点, 子节点) {
        if (节点.children.length > 第n个子节点) {
            节点.children[个子节点] = 子节点
            子节点.up = 节点
        }
    },
    del子节点: function (节点, 第n个子节点) {
        if (节点.children.length > 第n个子节点) {
            节点.children.splice(第n个子节点, 1)
        }
    },
    search: function (节点, 节点id) {
        return this.down直到(节点, function (nd) {
            if (nd.id == 节点id)
                return nd;
            else
                return null;
        })
    },
    downArr: function (数组, call) {
        if (数组 && call)
            for (let i = 0; i < 数组.length; ++i) {
                let 子节点 = 数组[i];
                // console.log("子节点", key, 子节点)
                this.downall(子节点, call);
            }
    },
    downArr直到: function (数组, call) {
        if (数组 && call)
            for (let i = 0; i < 数组.length; ++i) {
                let 子节点 = 数组[i];
                // console.log("子节点", key, 子节点)
                this.downall(子节点, call);
            }
    },
    downall: function (节点, call) {
        if (节点 == null || call == null) return;
        call(节点);
        if (节点.hasOwnProperty("children")) {
            for (let i = 0; i < 节点.children.length; ++i) {
                let 子节点 = 节点.children[i];
                // console.log("子节点", key, 子节点)
                this.downall(子节点, call);
            }
        }
    },
    down直到: function (节点, call) {
        if (节点 == null || call == null) return null;
        let flag = call(节点);
        if (flag != null) {          //如果为true 停止遍历
            return 节点;
        }//如果为false 继续遍历
        if (节点.hasOwnProperty("children")) {
            for (let i = 0; i < 节点.children.length; ++i) {
                children
                let 子节点 = 节点.children[i];
                let obj = this.down直到(子节点, call);
                if (obj != null) return obj;
            }
        }
        return null;
    },
    upall: function (节点, call) {
        if (节点 == null || call == null) return;
        call(节点)
        this.upall(节点.up, call)
    },
    up直到: function (节点, call) {
        if (节点 == null || call == null) return null;
        // console.log(节点)
        let obj = call(节点)
        if (obj != null)
            return obj;
        return this.up直到(节点.up, call);
    }

}


// let nd = Node.createNew('1',  1 );
// let nd1 = Node.createNew('2',  2 );
// let nd2 = Node.createNew('3',  3 );
// let nd21 = Node.createNew('4',  4 );
// let nd3 = Node.createNew('5',  5 );
// let nd31 = Node.createNew('6',  6 );
// let nd32 = Node.createNew('7',  7 );
// let nd311 = Node.createNew('8',  8 );
// let nd3111 = Node.createNew('9',  9 );

// Node.add子节点(nd, nd1)
// Node.add子节点(nd, nd2)
// Node.add子节点(nd2, nd21)
// Node.add子节点(nd, nd3)
// Node.add子节点(nd3, nd31)
// Node.add子节点(nd3, nd32)
// Node.add子节点(nd31, nd311)
// Node.add子节点(nd311, nd3111)
// Node.downall(nd, function (ndd) {
//     console.log(ndd)
// })
// let ndd = Node.search(nd, '8');
// console.log(ndd)

// let ndd = Node.up直到(nd311, function (nddd) {
//     if (nddd.id == '5') {
//         console.log(nddd)
//         return nddd
//     }    else
//         return null;
// })


// Node.upall(nd3111, function (nddd) {
//     console.log(nddd.id)
// })
export default Node;